package middleware

import (
	"lsgfish/server/internal/tool"
	"reflect"
	"regexp"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
)

// ValidatorMiddleware 返回一个中间件，用于验证请求参数并返回自定义错误信息
func ValidatorMiddleware() gin.HandlerFunc {
	// 获取 gin binding 中的验证器实例
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		// 注册自定义的校验方法
		// v.RegisterValidation("mobile", validateMobile)
		v.RegisterValidation("localpath", validateLocalPath)

		// 注册一个函数来从结构体字段标签中获取自定义错误信息
		v.RegisterTagNameFunc(func(fld reflect.StructField) string {
			msg := fld.Tag.Get("msg")
			return msg
		})
	}

	return func(c *gin.Context) {
		c.Next()

		// 检查是否有验证错误
		if len(c.Errors) > 0 {
			for _, e := range c.Errors {
				// 检查是否是验证器错误
				if errs, ok := e.Err.(validator.ValidationErrors); ok && len(errs) > 0 {
					// 获取第一个验证错误
					err := errs[0]

					if msg, exists := tagErrorMessages[err.Tag()]; exists {
						tool.Err(c, msg)
						c.Abort()
						return
					}

					// 使用我们注册的 TagNameFunc 返回的错误信息
					msg := err.Field()
					if msg == "" {
						msg = "请求参数无效"
					}
					tool.Err(c, msg)
					c.Abort()
					return
				} else {
					// 对于非验证错误
					tool.Err(c, "请求参数无效")
					c.Abort()
					return
				}
			}
		}
	}
}

// validateMobile 自定义手机号验证函数
// func validateMobile(fl validator.FieldLevel) bool {
//     mobile := fl.Field().String()
//     // 使用正则表达式验证手机号
//     ok, _ := regexp.MatchString(`^1[3-9]\d{9}$`, mobile)
//     return ok
// }

// 为特定验证标签提供自定义错误信息
var tagErrorMessages = map[string]string{
	"localpath": "请提供有效的本地文件路径",
	// 可以添加更多标签对应的错误信息
	// "mobile": "请提供有效的手机号码",
	// "required": "此字段不能为空",
}

// validateLocalPath 验证路径是否为本地文件路径
func validateLocalPath(fl validator.FieldLevel) bool {
	path := fl.Field().String()

	// 检查路径是否为空
	if path == "" {
		return false
	}

	// 检查是否包含网络协议前缀
	if strings.HasPrefix(path, "http://") ||
		strings.HasPrefix(path, "https://") ||
		strings.HasPrefix(path, "ftp://") ||
		strings.HasPrefix(path, "sftp://") {
		return false
	}

	// 检查是否为有效的本地路径格式
	// Windows路径格式 (如 C:\folder\file.txt 或 \\server\share)
	windowsPathPattern := `^([a-zA-Z]:\\|\\\\)[^<>:"/\\|?*]+$`
	// Unix/Linux路径格式 (如 /usr/local/bin 或 ./file.txt 或 ~/documents)
	unixPathPattern := `^(/[^<>:"/\\|?*]+|\.{1,2}/|~/).*$`

	isWindowsPath, _ := regexp.MatchString(windowsPathPattern, path)
	isUnixPath, _ := regexp.MatchString(unixPathPattern, path)

	return isWindowsPath || isUnixPath
}
